/**
 * 
 */
package edu.gatech.oad.yuno;

import java.util.Map;
import android.database.sqlite.*;
import android.database.Cursor;
import android.content.ContentValues;
import android.content.Context;

/**
 * Represents an object in the database.
 * @author michael
 *
 */
public abstract class Model {
	protected static Context context;
	long id = 0;
	String table_name;
	Map<String,Object> data;
	
	public static void setContext(Context c) {
		Model.context = c;
	}
	
	/**
	 * If this object has an ID, load its data from the database. Otherwise,
	 * load null for each key.
	 * @return true if successful, false otherwise
	 */
	protected boolean load() {
		TodoListOpenHelper helper = new TodoListOpenHelper(Model.context);
		SQLiteDatabase db = helper.getReadableDatabase();
		String query = "SELECT * FROM " + table_name;
		if (id != 0) query += " WHERE id=" + id;
		query += " LIMIT 1";
		
		Cursor c = db.rawQuery(query, null);
		if (c != null) {
            String[] cols = c.getColumnNames();
            if (id == 0) {
            	for (String col : cols) {
            		data.put(col, null);
            	}
            } else {
        		c.moveToFirst();
            	for (int i = 0; i < cols.length; i++) {
            		if (!cols[i].equals("id"))
            			data.put(cols[i], c.getString(i)); //TODO - check column type
            	}
            }
            db.close();
            return true;
        }
		db.close();
		return false;
	}
	
	public void validate() throws ValidationException {
		return;
	}
	
	/**
	 * Save the current state of this model back to the database.
	 * @return true if successful, false on error
	 */
	public boolean save() {
		try { validate(); }
		catch (ValidationException e) { return false; }
		TodoListOpenHelper helper = new TodoListOpenHelper(Model.context);
		SQLiteDatabase db = helper.getWritableDatabase();
		
		db.beginTransaction();
		try {
			ContentValues values = new ContentValues();
			for (Map.Entry<String,Object> e : data.entrySet()) {
				if (e.getValue() != null)
					values.put(e.getKey(), e.getValue().toString());
			}
			if (id == 0) { 
				values.remove("id");
				id = db.insert(table_name, null, values);
			} else {
				values.put("id", id);
				db.update(table_name, values, "id="+id, null);
			}
			
			db.setTransactionSuccessful();
		} finally {
			db.endTransaction();
		}
		db.close();
		return true;
	}
	
	/**
	 * Delete this model from the database.
	 * @return true if successful, false on error
	 */
	public boolean delete() {
		if (id != 0) {
			TodoListOpenHelper helper = new TodoListOpenHelper(Model.context);
			SQLiteDatabase db = helper.getWritableDatabase();
			
			db.beginTransaction();
			try {
				db.delete(table_name, "id="+id, null);
				id = 0;
				db.setTransactionSuccessful();
			} finally {
				db.endTransaction();
				db.close();
			}
		}
		return true;
	}
	
	/**
	 * Return this object's ID.
	 * @return the object's ID or 0 if object has not been saved
	 */
	public long getId() {
		return id;
	}
	
	public boolean equals(Object o) {
		if (!(o instanceof Model)) return false;
		Model m = (Model)o;
		if (m.id==0 || this.id==0) return false; //no way to tell if they're the same
		return (m.table_name.equals(this.table_name) && m.id==this.id);
	}
	
	protected boolean getBoolean(String key) {
		return (!(data.get(key) == null) && !data.get(key).equals("0"));
	}
	
	protected void setBoolean(String key, boolean val) {
		if (val) {
			data.put(key, "1");
		} else {
			data.put(key, "0");
		}
	}
	
	protected long getLong(String key) {
		try {
			long id = Long.parseLong((String)data.get(key));
			return id;
		} catch (NumberFormatException e) {
			return -1;
		}
	}
	
	protected int getInt(String key) {
		try {
			return Integer.parseInt((String)data.get(key));
		} catch (NumberFormatException e) {
			return -1;
		}
	}
	
	protected double getDouble(String key) {
		try {
			return Double.parseDouble((String)data.get(key));
		} catch (NumberFormatException e) {
			return -1;
		}
	}
}
